/**
 * echarts地图一般投射算法
 * modify from GeoMap v0.5.3 https://github.com/x6doooo/GeoMap
 * 
 * @desc echarts基于Canvas，纯Javascript图表库，提供直观，生动，可交互，可个性化定制的数据统计图表。
 * @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
 *
 */


var PathShape = require('zrender/shape/Path');
function toFloat(str) {
    return parseFloat(str || 0);
}
function getBbox(root) {
    var svgNode = root.firstChild;
    // Find the svg node
    while (!(svgNode.nodeName.toLowerCase() == 'svg' && svgNode.nodeType == 1)) {
        svgNode = svgNode.nextSibling;
    }
    var x = toFloat(svgNode.getAttribute('x'));
    var y = toFloat(svgNode.getAttribute('y'));
    var width = toFloat(svgNode.getAttribute('width'));
    var height = toFloat(svgNode.getAttribute('height'));
    return {
        left: x,
        top: y,
        width: width,
        height: height
    };
}
function geoJson2Path(root, transform) {
    var scale = [
        transform.scale.x,
        transform.scale.y
    ];
    var elList = [];
    function _getShape(root) {
        var tagName = root.tagName;
        if (shapeBuilders[tagName]) {
            var obj = shapeBuilders[tagName](root, scale);
            if (obj) {
                // Common attributes
                obj.scale = scale;
                obj.properties = { name: root.getAttribute('name') || '' };
                obj.id = root.id;
                extendCommonAttributes(obj, root);
                elList.push(obj);
            }
        }
        var shapes = root.childNodes;
        for (var i = 0, len = shapes.length; i < len; i++) {
            _getShape(shapes[i]);
        }
    }
    _getShape(root);
    return elList;
}
/**
     * 平面坐标转经纬度
     * @param {Array} p
     */
function pos2geo(obj, p) {
    var point = p instanceof Array ? [
        p[0] * 1,
        p[1] * 1
    ] : [
        p.x * 1,
        p.y * 1
    ];
    return [
        point[0] / obj.scale.x,
        point[1] / obj.scale.y
    ];
}
/**
     * 经纬度转平面坐标
     * @param {Array | Object} p
     */
function geo2pos(obj, p) {
    var point = p instanceof Array ? [
        p[0] * 1,
        p[1] * 1
    ] : [
        p.x * 1,
        p.y * 1
    ];
    return [
        point[0] * obj.scale.x,
        point[1] * obj.scale.y
    ];
}
function trim(str) {
    return str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
}
function extendCommonAttributes(obj, xmlNode) {
    var color = xmlNode.getAttribute('fill');
    var strokeColor = xmlNode.getAttribute('stroke');
    var lineWidth = xmlNode.getAttribute('stroke-width');
    var opacity = xmlNode.getAttribute('opacity');
    if (color && color != 'none') {
        obj.color = color;
        if (strokeColor) {
            obj.brushType = 'both';
            obj.strokeColor = strokeColor;
        } else {
            obj.brushType = 'fill';
        }
    } else if (strokeColor && strokeColor != 'none') {
        obj.strokeColor = strokeColor;
        obj.brushType = 'stroke';
    }
    if (lineWidth && lineWidth != 'none') {
        obj.lineWidth = parseFloat(lineWidth);
    }
    if (opacity && opacity != 'none') {
        obj.opacity = parseFloat(opacity);
    }
}
function parsePoints(str) {
    var list = trim(str).replace(/,/g, ' ').split(/\s+/);
    var points = [];
    for (var i = 0; i < list.length;) {
        var x = parseFloat(list[i++]);
        var y = parseFloat(list[i++]);
        points.push([
            x,
            y
        ]);
    }
    return points;
}
// Regular svg shapes
var shapeBuilders = {
    path: function (xmlNode, scale) {
        var path = xmlNode.getAttribute('d');
        var rect = PathShape.prototype.getRect({ path: path });
        return {
            shapeType: 'path',
            path: path,
            cp: [
                (rect.x + rect.width / 2) * scale[0],
                (rect.y + rect.height / 2) * scale[1]
            ]
        };
    },
    rect: function (xmlNode, scale) {
        var x = toFloat(xmlNode.getAttribute('x'));
        var y = toFloat(xmlNode.getAttribute('y'));
        var width = toFloat(xmlNode.getAttribute('width'));
        var height = toFloat(xmlNode.getAttribute('height'));
        return {
            shapeType: 'rectangle',
            x: x,
            y: y,
            width: width,
            height: height,
            cp: [
                (x + width / 2) * scale[0],
                (y + height / 2) * scale[1]
            ]
        };
    },
    line: function (xmlNode, scale) {
        var x1 = toFloat(xmlNode.getAttribute('x1'));
        var y1 = toFloat(xmlNode.getAttribute('y1'));
        var x2 = toFloat(xmlNode.getAttribute('x2'));
        var y2 = toFloat(xmlNode.getAttribute('y2'));
        return {
            shapeType: 'line',
            xStart: x1,
            yStart: y1,
            xEnd: x2,
            yEnd: y2,
            cp: [
                (x1 + x2) * 0.5 * scale[0],
                (y1 + y2) * 0.5 * scale[1]
            ]
        };
    },
    circle: function (xmlNode, scale) {
        var cx = toFloat(xmlNode.getAttribute('cx'));
        var cy = toFloat(xmlNode.getAttribute('cy'));
        var r = toFloat(xmlNode.getAttribute('r'));
        return {
            shapeType: 'circle',
            x: cx,
            y: cy,
            r: r,
            cp: [
                cx * scale[0],
                cy * scale[1]
            ]
        };
    },
    ellipse: function (xmlNode, scale) {
        var cx = parseFloat(xmlNode.getAttribute('cx') || 0);
        var cy = parseFloat(xmlNode.getAttribute('cy') || 0);
        var rx = parseFloat(xmlNode.getAttribute('rx') || 0);
        var ry = parseFloat(xmlNode.getAttribute('ry') || 0);
        return {
            shapeType: 'ellipse',
            x: cx,
            y: cy,
            a: rx,
            b: ry,
            cp: [
                cx * scale[0],
                cy * scale[1]
            ]
        };
    },
    polygon: function (xmlNode, scale) {
        var points = xmlNode.getAttribute('points');
        var min = [
            Infinity,
            Infinity
        ];
        var max = [
            -Infinity,
            -Infinity
        ];
        if (points) {
            points = parsePoints(points);
            for (var i = 0; i < points.length; i++) {
                var p = points[i];
                min[0] = Math.min(p[0], min[0]);
                min[1] = Math.min(p[1], min[1]);
                max[0] = Math.max(p[0], max[0]);
                max[1] = Math.max(p[1], max[1]);
            }
            return {
                shapeType: 'polygon',
                pointList: points,
                cp: [
                    (min[0] + max[0]) / 2 * scale[0],
                    (min[1] + max[1]) / 2 * scale[0]
                ]
            };
        }
    },
    polyline: function (xmlNode, scale) {
        var obj = shapeBuilders.polygon(xmlNode, scale);
        return obj;
    }
};
module.exports = {
    getBbox: getBbox,
    geoJson2Path: geoJson2Path,
    pos2geo: pos2geo,
    geo2pos: geo2pos
} || module.exports;;